package org.angmarch.views;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;

/**

 */
public class WaveView extends View {

    private static final int DEFAULT_WIDTH = 100;
    private static final int DEFAULT_HEIGHT = 50;
    private static final float MIN_AMPLITUDE = 0.275f;
    private float mPrimaryWidth = 1.0f;
    private float mSecondaryWidth = 0.5f;
    private float mAmplitude = MIN_AMPLITUDE;
    private int mWaveColor = Color.DKGRAY;
    private int mDensity = 2;
    private int mWaveCount = 5;
    private float mFrequency = 0.1875f;
    private float mPhaseShift = -0.1875f;
    private float mPhase = mPhaseShift;

    private Paint mPrimaryPaint;
    private Paint mSecondaryPaint;

    private Path mPath;

    private float mLastX;
    private float mLastY;
    private int[] clolors ={Color.RED,Color.GREEN,Color.YELLOW,Color.BLUE};

    public WaveView(Context context) {
        this(context, null);
    }

    public WaveView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WaveView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initialize();
    }

    private void initialize() {
        mPrimaryPaint = new Paint();
        mPrimaryPaint.setStrokeWidth(mPrimaryWidth);
        mPrimaryPaint.setAntiAlias(true);
        mPrimaryPaint.setStyle(Paint.Style.STROKE);
        mPrimaryPaint.setColor(mWaveColor);

        mSecondaryPaint = new Paint();
        mSecondaryPaint.setStrokeWidth(mSecondaryWidth);
        mSecondaryPaint.setAntiAlias(true);
        mSecondaryPaint.setStyle(Paint.Style.STROKE);
        mSecondaryPaint.setColor(mWaveColor);

        mPath = new Path();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private int measureWidth(int widthMeasureSpec) {

        int result ;
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        if(mode==MeasureSpec.EXACTLY){
            result = size;
        }else{
            result = DEFAULT_WIDTH;
            if(mode==MeasureSpec.AT_MOST){
                result = Math.min(result,size);
            }
        }
        return result;
    }

    private int measureHeight(int heightMeasureSpec) {

        int result ;
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        if(mode==MeasureSpec.EXACTLY){
            result = size;
        }else{
            result = DEFAULT_HEIGHT;
            if(mode==MeasureSpec.AT_MOST){
                result = Math.min(result,size);
            }
        }
        return result;
    }

    /**
     * 0----0.2之间     * @param waveHeight
     */
    public void setWaveHeight(float waveHeight){

        mAmplitude = waveHeight;
        invalidate();
    }


    @Override
    public void setVisibility(int visibility) {
        //优化
        if(visibility!=VISIBLE){
            setWaveHeight(0);
        }else{
            setWaveHeight(0.2f);
        }


        super.setVisibility(visibility);
    }

    private int mHeight;
    private int mWidth;
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        this.mHeight = h;
        this.mWidth = w;
        LinearGradient linearGradient = new LinearGradient(0, mHeight * 1.0f / 2, mWidth, mHeight * 1.0f / 2, clolors, null, Shader.TileMode.MIRROR);
        mPrimaryPaint.setShader(linearGradient);
        mSecondaryPaint.setShader(linearGradient);
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int width = getWidth();
        int height = getHeight();

        for (int l = 0; l < mWaveCount; ++l) {
            float midH = height / 2.0f;
            float midW = width / 2.0f;

            float maxAmplitude = midH / 2f - 4.0f;
            float progress = 1.0f - l * 1.0f / mWaveCount;
            float normalAmplitude = (1.5f * progress - 0.5f) * mAmplitude;

            float multiplier = (float) Math.min(1.0, (progress / 3.0f * 2.0f) + (1.0f / 3.0f));

            if (l != 0) {
                mSecondaryPaint.setAlpha((int) (multiplier * 255));
            }

            mPath.reset();
            for (int x = 0; x < width + mDensity; x += mDensity) {
                float scaling = 1f - (float) Math.pow(1 / midW * (x - midW), 2);
                float y = scaling * maxAmplitude * normalAmplitude * (float) Math.sin(
                        180 * x * mFrequency / (width * Math.PI) + mPhase) + midH;
                if (x == 0) {
                    mPath.moveTo(x, y);
                } else {
                    mPath.lineTo(x, y);
                }

                mLastX = x;
                mLastY = y;
            }

            if (l == 0) {
                canvas.drawPath(mPath, mPrimaryPaint);
            } else {
                canvas.drawPath(mPath, mSecondaryPaint);
            }
        }

        mPhase += mPhaseShift;

        if(mAmplitude>0.01){
            invalidate();

        }
    }
}